/*
 * Copyright 2008 Jens Meiss
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License. 
 * You may obtain a copy of the License at 
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package hmvc.j2me.framework.rms;

import hmvc.j2me.controller.AController;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Vector;

import javax.microedition.rms.InvalidRecordIDException;
import javax.microedition.rms.RecordComparator;
import javax.microedition.rms.RecordEnumeration;
import javax.microedition.rms.RecordFilter;
import javax.microedition.rms.RecordListener;
import javax.microedition.rms.RecordStore;
import javax.microedition.rms.RecordStoreException;
import javax.microedition.rms.RecordStoreFullException;
import javax.microedition.rms.RecordStoreNotFoundException;
import javax.microedition.rms.RecordStoreNotOpenException;

/**
 * 
 * 
 * @author jens.meiss
 */
public abstract class ObjectStore extends AController {

	private RecordStore recordStore;

	protected void addRecordListener(RecordListener listener) {
		recordStore.addRecordListener(listener);
	}

	protected void close() {
		try {
			if (recordStore != null) {

				recordStore.closeRecordStore();

			}
		} catch (RecordStoreNotOpenException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (RecordStoreException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	protected void deserializeRecord(byte[] data,
			IRMSSerializeable serializeable) throws IOException {
		ByteArrayInputStream byteStream = new ByteArrayInputStream(data);
		DataInputStream dataInputStream = new DataInputStream(byteStream);

		serializeable.deserialize(dataInputStream);
	}

	protected RecordEnumeration enumerateRecords(RecordFilter filter,
			RecordComparator comparator, boolean keepUpdated)
			throws RecordStoreNotOpenException {
		return recordStore.enumerateRecords(filter, comparator, keepUpdated);
	}

	protected int getNumRecords() throws RecordStoreNotOpenException {
		return recordStore.getNumRecords();
	}

	protected void getRecord(int recordId, IRMSSerializeable serializeable)
			throws RecordStoreNotOpenException, InvalidRecordIDException,
			RecordStoreException, IOException {
		byte[] data = recordStore.getRecord(recordId);
		deserializeRecord(data, serializeable);
	}

	protected abstract String getRecordStoreName();

	protected int getSizeAvailable() throws RecordStoreNotOpenException {
		return recordStore.getSizeAvailable();
	}

	/**
	 * returns a Vector containing all Records
	 * 
	 * @return Vector
	 */
	protected Vector getVectorRecords(IRMSSerializeable serializeable,
			RecordFilter filter, RecordComparator comparator,
			boolean keepUpdated) {

		Vector vector = new Vector();
		try {

			/*
			 * Über alle Records iterieren
			 */
			RecordEnumeration enumeration = enumerateRecords(filter,
					comparator, keepUpdated);
			while (enumeration.hasNextElement()) {

				IRMSSerializeable serializeableNext = serializeable
						.getInstance();

				deserializeRecord(enumeration.nextRecord(), serializeable);
				vector.addElement(serializeable);

				// TODO prüfen ob das sinnvoll ist
				serializeable = serializeableNext;
			}

		} catch (RecordStoreException e) {
			// TODO: handle exception
		} catch (IOException e) {
			// TODO: handle exception
		}

		return vector;

	}

	protected void open() {

		try {
			recordStore = RecordStore.openRecordStore(getRecordStoreName(),
					true);
		} catch (RecordStoreFullException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (RecordStoreNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (RecordStoreException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	/**
	 * removes the object with the given id from the RecordStore
	 * 
	 * @param id
	 * @throws RecordStoreException
	 * @throws InvalidRecordIDException
	 * @throws RecordStoreNotOpenException
	 */
	protected void remove(int id) throws RecordStoreNotOpenException,
			InvalidRecordIDException, RecordStoreException {

		recordStore.deleteRecord(id);

	}

	protected void removeRecordListener(RecordListener listener) {
		recordStore.removeRecordListener(listener);
	}

	/**
	 * serializes the record
	 * 
	 * @param record
	 * @return byte[] version of the record
	 * @throws IOException
	 */
	private byte[] serializeRecord(IRMSSerializeable record) throws IOException {
		ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
		DataOutputStream out = new DataOutputStream(byteStream);

		record.serialize(out);

		return byteStream.toByteArray();
	}

	/**
	 * adds a new Record to the RecordStore and sets automatically the RecordId
	 * 
	 * @param object
	 * @throws RecordStoreException
	 * @throws IOException
	 */
	protected void store(IRMSSerializeable record) throws RecordStoreException,
			IOException {

		/*
		 * Id für das Objekt holen
		 */
		record.setRecordId(recordStore.getNextRecordID());

		/*
		 * Object serialisieren
		 */
		byte[] data = serializeRecord(record);

		/*
		 * record hinzufügen
		 */
		recordStore.addRecord(data, 0, data.length);

	}

	protected void update(IRMSSerializeable record) throws IOException,
			RecordStoreNotOpenException, InvalidRecordIDException,
			RecordStoreFullException, RecordStoreException {

		byte[] data = serializeRecord(record);
		recordStore.setRecord(record.getRecordId(), data, 0, data.length);

	}

}
